/**
 * Copyright (c) 2010-2020 by skzr.org
 * All rights reserved.
 * @Author <a href="mailto:skzr.org@gmail.com">skzr.org</a>
 * @date 2011-3-16 下午11:15:51
 */
package org.skzr.logging.util;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.skzr.logging.util.impl.ResourceFile;
import org.skzr.logging.util.impl.ResourceJarEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @author <a href="mailto:skzr.org@gmail.com">skzr.org</a>
 * @version 1.0.0
 * @since JDK1.6
 */
public final class UtilSlf4jLocal {
	private static final Logger LOGGER = LoggerFactory.getLogger(UtilSlf4jLocal.class);
	private static final String PROPERTIES = ".properties";
	
	private UtilSlf4jLocal() {
	}
	
	/**
	 * 获取用于加载资源的ClassLoader.<br>
	 * 获取有效加载器次序
	 * <ol>
	 * 	<li>指定的加载器</li>
	 * 	<li>Thread.currentThread().getContextClassLoader()</li>
	 * 	<li>UtilResource.class.getClassLoader()</li>
	 * </ol>
	 * @param classLoader 指定加载器
	 * @return 有效的资源加载器
	 */
	private static ClassLoader getClassLoader(ClassLoader classLoader) {
		if (classLoader != null) return classLoader;
		
		ClassLoader ret = Thread.currentThread().getContextClassLoader();
		return ret == null ? UtilSlf4jLocal.class.getClassLoader() : ret; // NOPMD by skzrorg on 11-3-17 下午9:05
	}
	
	/**
	 * 提取文件信息
	 * @param propertiesKey 国际化文件(org.skzr.xxx.**.message)
	 * @return String[2]{父路径, 国际化文件名}
	 */
	private static String[] determineDir(String propertiesKey) {
		int pos = propertiesKey.lastIndexOf('.');
		return pos == -1 ? new String[]{"", propertiesKey}
			: new String[]{propertiesKey.substring(0, pos).replace('.', '/'), propertiesKey.substring(pos + 1)};
	}
	
	/**
	 * 在目录中搜索文件.
	 * @param dirURL 目录
	 * @param fileName 国际化文件名
	 * @return List&lt;IResouce资源&gt;
	 */
	private static List<IResource> doFindInDir(URL dirURL, String fileName) {
		List<IResource> resources = new ArrayList<IResource>();
		for (File file : new File(dirURL.getFile()).listFiles()) {
			if (file.isFile() && file.getName().startsWith(fileName) && file.getName().endsWith(PROPERTIES)) {
				LOGGER.debug("[LOG I10N]find: {}", file);
				resources.add(new ResourceFile(file));
			}
		}
		return resources;
	}
	
	/**
	 * 在jar文件中搜索.
	 * @param dirURL 目录
	 * @param fileName 国际化文件名
	 * @return List&lt;IResouce资源&gt;
	 * @throws IOException IO访问异常
	 */
	private static List<IResource> doFindInJar(URL dirURL, String fileName) throws IOException {
		JarURLConnection jarCon = (JarURLConnection) dirURL.openConnection();
		jarCon.setUseCaches(false);
		List<IResource> result = new ArrayList<IResource>();
		
		JarEntry jarEntry = jarCon.getJarEntry();
		String rootEntryPath = jarEntry == null ? "" : jarEntry.getName();
		if (!"".equals(rootEntryPath) && !rootEntryPath.endsWith("/")) {
			rootEntryPath = rootEntryPath + "/"; // NOPMD by skzrorg on 11-3-17 下午11:47
		}

		JarFile jarFile = jarCon.getJarFile(); // NOPMD by skzrorg on 11-3-22 上午12:52
		for (Enumeration<JarEntry> entries = jarCon.getJarFile().entries(); entries.hasMoreElements();) {
			JarEntry entry = entries.nextElement();
			String entryPath = entry.getName();
			if (entryPath.startsWith(rootEntryPath)) {
				String relativePath = entryPath.substring(rootEntryPath.length());
				if (relativePath.indexOf('/') == -1 && relativePath.startsWith(fileName) && relativePath.endsWith(PROPERTIES)) {
					LOGGER.debug("[LOG I10N]jar: {}", entry);
					result.add(new ResourceJarEntry(jarFile, rootEntryPath, entry));
				}
			}
		}
		return result;
	}

	/**
	 * 从所有路径读取资源.<br>
	 * @param locationPattern	资源完整路径
	 * @return	List&lt;资源&gt;
	 */
	public static List<IResource> getResources(String locationPattern) {
		return getResources(null, locationPattern);
	}
	
	/**
	 * 从所有路径读取国际化文件.<br>
	 * @param classLoader 类加载器
	 * @param propertiesKey	国际化文件(org.skzr.xxx.**.message)
	 * @return	List&lt;国际化文件&gt;
	 */
	public static List<IResource> getResources(ClassLoader classLoader, String propertiesKey) {
		LOGGER.debug("[LOG I10N]getResources({}, {})", classLoader, propertiesKey);
		ClassLoader loader = getClassLoader(classLoader);
		String[] paths = determineDir(propertiesKey);
		
		List<IResource> resources = new ArrayList<IResource>();
		try {
			for (Enumeration<URL> enumeration = loader.getResources(paths[0]); enumeration.hasMoreElements();) {
				URL url = enumeration.nextElement();
				LOGGER.debug("[LOG I10N]search in: {}", url);
				if ("jar".equals(url.getProtocol())) {
					resources.addAll(doFindInJar(url, paths[1]));
				} else {
					resources.addAll(doFindInDir(url, paths[1]));
				}
			}
			return resources;
		} catch (IOException e) {
			throw new IllegalStateException("[LOG I10N]load failed!", e);
		}
	}
	
	public static boolean isEmptyStr(String value) {
		return isEmptyStr(value, true);
	}
	public static boolean isEmptyStr(String value, boolean trim) {
		return value == null || value.isEmpty() || (trim && value.trim().isEmpty());
	}

	public static void close(Closeable closeable) {
		if (closeable != null) {
			try {
				closeable.close();
			} catch (IOException e) {
				LOGGER.warn("[LOG I10N]closeable fail!", e);
			}
		}
	}

}
